package glassline;

import glassline.interfaces.Conveyor;
import glassline.interfaces.Sensor;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import transducer.TChannel;
import transducer.TEvent;
import transducer.TReceiver;
import transducer.Transducer;
import agent.Agent;

public class SensorAgent extends Agent implements TReceiver, Sensor {

	Conveyor parent = null; // Parent factory agent.
	Conveyor parentPrevNeighbor = null;
	
	boolean sensing = false;
	
	public List<Boolean> triggers = Collections.synchronizedList(new ArrayList<Boolean>());

	public SensorAgent(Transducer t, Conveyor parent, Conveyor parentPrevNeighbor) {
		super(t);
		
		this.parent = parent;
		this.parentPrevNeighbor = parentPrevNeighbor;
		
		// Register channel with the transducer
		myTransducer.register(this, TChannel.Sensors);
	}

	// Messages
	
	/* (non-Javadoc)
	 * @see glassline.Sensor#msgSense(boolean)
	 */
	@Override
	public void msgSense(boolean sensing) { // Sent from GUISensor
		triggers.add(sensing);
		stateChanged();
	}
	
	/* (non-Javadoc)
	 * @see glassline.Sensor#pickAndExecuteAnAction()
	 */
	@Override
	public boolean pickAndExecuteAnAction() {
		if (triggers.isEmpty()) return false;

		boolean sensing = triggers.get(0);
		triggers.remove(0);

		SensedObject(sensing);
		
		return true;
	}
	
	// Transducer event listener.
	public void eventFired(TChannel channel, TEvent event, Object[] args) {
		if (channel != TChannel.Sensors) return;
		
		// Check the event fired.
		if (event == TEvent.SENSED_GLASS) {
			sensing = true;
			this.msgSense(true);
		}
		else if (event == TEvent.UNSENSED_GLASS) {
			sensing = false;
			this.msgSense(false);
		}
	}
	
	// Actions
	
	void SensedObject(boolean sensing) {
		if (parent == null) {
			// Problem
			return;
		}
		
		parent.msgSensorNotify(this, sensing);
		if (parentPrevNeighbor != null) parentPrevNeighbor.msgNextSensorNotify(parentPrevNeighbor, this, sensing);
	}

	// Misc methods.
	
	public void setParent(Conveyor p) {
		parent = p;
	}
	
	public void setParentPrevNeighbor(Conveyor p) {
		this.parentPrevNeighbor = p;
	}

	// Unit test stufff
	/* (non-Javadoc)
	 * @see glassline.Sensor#printData()
	 */
	@Override
	public void printData() {
		System.out.println("Parent: " + parent);
		System.out.println("Sensing: " + sensing);
		//System.out.println("Sensor states (sensing or not): " + triggers.toString());
	}
}
